package com.red.star.wechat.data.repository;

import com.red.star.wechat.data.core.constant.MessageConstant;
import com.red.star.wechat.data.core.constant.MongoConstant;
import com.red.star.wechat.data.entity.ChatMessage;
import com.red.star.wechat.data.entity.ChatSession;
import com.red.star.wechat.data.entity.Group;
import com.red.star.wechat.data.mappers.GroupMapper;
import com.red.star.wechat.data.utils.CheckUtil;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author nofish.yan@gmail.com
 * @date 2018/2/7.
 * 聊天记录数据访问类
 */
@Repository
public class ChatSessionRepository {

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private GroupMapper groupMapper;

    /**
     * 创建新的群聊天会话
     *
     * @param cFansId C端用户ID
     * @param groupId 群组ID(接待组/联盟组)
     * @param scene   发起聊天场景
     * @return 聊天会话
     */
    public ChatSession createGroupChatSession(Integer cFansId, Integer groupId, Integer scene) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("group_id").is(groupId).and("enable").is(true));
        Update update = Update.update("c_fans_id", cFansId)
                .set("group_id", groupId)
                .set("resp", false)
                .set("scene", scene)
                .set("create_time", new Date())
                .set("update_time", new Date());
        Group group = groupMapper.selectByPrimaryKey(groupId);
        if (group != null && group.getType() != null) {
            if (group.getType() == 0) {
                // 接待组聊天
                update.set("type", MessageConstant.CHAT_TYPE_C2GROUP_RECEPTION);
            } else if (group.getType() == 1) {
                // 联盟组聊天
                update.set("type", MessageConstant.CHAT_TYPE_C2GROUP_UNION);
            }
        }
        int num = mongoTemplate.upsert(query, update, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION).getN();
        if (num > 0) {
            return findGroupChatSession(cFansId, groupId);
        }
        return null;
    }

    /**
     * 创建新的群聊天会话（E端）
     *
     * @param adminId E端用户ID
     * @param groupId 群组ID(接待组/联盟组)
     * @param scene   发起聊天场景
     * @return 聊天会话
     */
    public ChatSession createGroupAdminChatSession(Integer adminId, Integer groupId, Integer scene) {
        Query query = Query.query(Criteria.where("admin_id").is(adminId).and("group_id").is(groupId).and("enable").is(true));
        Update update = Update.update("adminId", adminId)
                .set("group_id", groupId)
                .set("resp", false)
                .set("scene", scene)
                .set("create_time", new Date())
                .set("update_time", new Date())
                .set("type", MessageConstant.CHAT_TYPE_ADMIN2GROUP_RECEPTION);
        int num = mongoTemplate.upsert(query, update, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION).getN();
        if (num > 0) {
            return findGroupAdminChatSession(adminId, groupId);
        }
        return null;
    }

    /**
     * 创建新的单聊会话
     *
     * @param cFansId    C端用户ID
     * @param bFansId    B端用户ID
     * @param employeeId 导购ID
     * @param scene      发起聊天场景
     * @return 聊天会话
     */
    public ChatSession createP2PChatSession(Integer cFansId, Integer bFansId, Integer employeeId, Integer scene) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("b_fans_id").is(bFansId).and("enable").is(true));
        Update update = Update.update("c_fans_id", cFansId)
                .set("b_fans_id", bFansId)
                .set("resp", false)
                .set("scene", scene)
                .set("last_scene", scene)
                .set("employee_id", employeeId)
                .set("type", MessageConstant.CHAT_TYPE_C2B)
                .set("create_time", new Date())
                .set("update_time", new Date());
        int num = mongoTemplate.upsert(query, update, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION).getN();
        if (num > 0) {
            return findFansGuideChatSession(cFansId, bFansId);
        }
        return null;
    }

    /**
     * 创建E端管理员和c端私聊
     *
     * @return
     */
    public ChatSession createAdminChatSession(Integer cFansId, Integer adminId, Integer scene) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("admin_id").is(adminId).and("enable").is(true));
        Update update = Update.update("c_fans_id", cFansId)
                .set("admin_id", adminId)
                .set("resp", false)
                .set("scene", scene)
                .set("type", MessageConstant.CHAT_TYPE_C2ADMIN)
                .set("create_time", new Date())
                .set("update_time", new Date());
        int num = mongoTemplate.upsert(query, update, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION).getN();
        if (num > 0) {
            return findFansAdminChatSession(cFansId, adminId);
        }
        return null;
    }

    /**
     * 创建首页聊天会话
     *
     * @param cFansId  C端用户ID
     * @param mallCode 商场code
     * @param scene    发起聊天场景
     * @return 聊天会话
     */
    public ChatSession createHomeChatSession(Integer cFansId, String mallCode, Integer scene) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("mall_code").is(mallCode).and("enable").is(true));
        Update update = Update.update("c_fans_id", cFansId)
                .set("mall_code", mallCode)
                .set("resp", false)
                .set("type", MessageConstant.CHAT_TYPE_C2MALL)
                .set("scene", scene)
                .set("create_time", new Date())
                .set("update_time", new Date());
        int num = mongoTemplate.upsert(query, update, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION).getN();
        if (num > 0) {
            return findHomeChatSession(cFansId, mallCode);
        }
        return null;
    }

    public ChatSession findHomeChatSession(Integer cFansId, String mallCode) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("mall_code").is(mallCode).and("enable").is(true));
        return mongoTemplate.findOne(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    /**
     * 保存单聊记录
     *
     * @param message 聊天消息
     * @return
     */
    public int updateP2PChatSession(ChatMessage message) {
        Query query = Query.query(Criteria.where("c_fans_id").is(message.getCFansId()).and("b_fans_id").is(message.getBFansId()).and("enable").is(true));
        Update update = Update.update("c_fans_id", message.getCFansId())
                .set("b_fans_id", message.getBFansId())
                .set("update_time", new Date());
        update.push("messages", message);
        return mongoTemplate.upsert(query, update, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION).getN();
    }

    /**
     * 更新聊天会话的消息
     *
     * @param message 聊天消息
     * @return
     */
    public int updateChatSession(ChatMessage message) {
        Query query = Query.query(Criteria.where("_id").is(message.getChatSessionId()));
        Update update = Update.update("update_time", new Date());
        boolean resp = message.getBFansId() != null || message.getAdminFansId() != null || message.getAdminId() != null;
        if (resp) {
            update.set("resp", true);
        }
        update.push("messages", message);
        return mongoTemplate.upsert(query, update, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION).getN();

    }

    /**
     * 查询指定聊天群的聊天记录(当前有效会话)
     *
     * @param cFansId C端用户ID
     * @param groupId 组ID
     * @return ChatSession
     */
    public ChatSession findGroupChatSession(Integer cFansId, Integer groupId) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("group_id").is(groupId).and("enable").is(true));
        return mongoTemplate.findOne(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    /**
     * 查询指定聊天群（E端群聊）的聊天记录(当前有效会话)
     *
     * @param adminId E端用户ID
     * @param groupId 组ID
     * @return ChatSession
     */
    public ChatSession findGroupAdminChatSession(Integer adminId, Integer groupId) {
        Query query = Query.query(Criteria.where("admin_id").is(adminId).and("group_id").is(groupId).and("enable").is(true));
        return mongoTemplate.findOne(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    /**
     * 查询用户与导购员之间的聊天记录(当前有效会话)
     *
     * @param cFansId 粉丝ID
     * @param bFansId 导购员ID
     * @return ChatSession
     */
    public ChatSession findFansGuideChatSession(Integer cFansId, Integer bFansId) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("b_fans_id").is(bFansId).and("enable").is(true));
        return mongoTemplate.findOne(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    /**
     * 查询用户与E端管理员之间的聊天记录(当前有效会话)
     *
     * @param cFansId 粉丝ID
     * @param adminId 导购员ID
     * @return ChatSession
     */
    public ChatSession findFansAdminChatSession(Integer cFansId, Integer adminId) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("admin_id").is(adminId).and("enable").is(true));
        return mongoTemplate.findOne(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    /**
     * 查询指定聊天群的聊天记录(所有会话)
     *
     * @param groupId 聊天群ID
     * @return ChatSession
     */
    public List<ChatSession> findAllGroupChatLog(Integer cFansId, Integer groupId) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("group_id").is(groupId));
        return mongoTemplate.find(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    /**
     * 查询用户与导购员之间的聊天记录(所有会话)
     *
     * @param cFansId C端用户ID
     * @param bFansId B端用户ID
     * @return ChatSession
     */
    public List<ChatSession> findAllFansGuideChatLog(Integer cFansId, Integer bFansId) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("b_fans_id").is(bFansId));
        return mongoTemplate.find(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    /**
     * 设置私聊聊天会话无效
     *
     * @param cFansId C端用户ID
     * @param bFansId B端用户ID
     * @return
     */
    public int disableP2PChatSession(Integer cFansId, Integer bFansId) {
        Query query = Query.query(Criteria.where("c_fans_id").is(cFansId).and("b_fans_id").is(bFansId).and("enable").is(true));
        Update update = Update.update("enable", false).set("update_time", new Date());
        return mongoTemplate.upsert(query, update, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION).getN();
    }

    /**
     * 根据ID查询聊天会话
     *
     * @param chatSessionId 聊天会话ID
     * @return 聊天会话
     */
    public ChatSession findChatSessionById(String chatSessionId) {
        Query query = Query.query(Criteria.where("_id").is(chatSessionId));
        return mongoTemplate.findOne(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    /**
     * 根据ID查询聊天会话(不包括聊天消息)
     *
     * @param chatSessionId 聊天会话ID
     * @return 聊天会话
     */
    public ChatSession findChatSessionByIdWithouMessage(String chatSessionId) {
        Query query = Query.query(Criteria.where("_id").is(chatSessionId));
        query.fields().include("_id")
                .include("c_fans_id")
                .include("b_fans_id")
                .include("admin_fans_id")
                .include("group_id")
                .include("mall_code")
                .include("create_time")
                .include("update_time")
                .include("enable");
        return mongoTemplate.findOne(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    public int updateLastScene(String chatSessionId, int scene) {
        Query query = Query.query(Criteria.where("_id").is(chatSessionId));
        Update update = Update.update("last_scene", scene)
                .set("update_time", new Date());
        return mongoTemplate.upsert(query, update, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION).getN();
    }

    /**
     * 查询B端导购员私聊的所有粉丝
     *
     * @param bFansId B端用户ID
     * @return 聊天会话
     */
    public List<ChatSession> findChatSessionByBFansId(Integer bFansId) {
        Query query = Query.query(Criteria.where("b_fans_id").is(bFansId));
        query.fields().include("c_fans_id");
        return mongoTemplate.find(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    /**
     * 设置指定聊天会话失效
     *
     * @param chatSessionId 聊天会话ID
     * @return
     */
    public int disableChatSession(String chatSessionId) {
        Query query = Query.query(Criteria.where("_id").is(chatSessionId));
        Update update = Update.update("enable", false).set("update_time", new Date());
        return mongoTemplate.upsert(query, update, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION).getN();
    }

    /**
     * 查询三十分钟内活跃的用户
     *
     * @return
     */
    public List<ChatSession> findChatSessionActiveInThirtyMinute() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, -30);
        Query query = Query.query(Criteria.where("enable").is(true))
                .addCriteria(Criteria.where("update_time").gt(calendar.getTime()));
        return mongoTemplate.find(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    public List<ChatSession> listChatSessionByCreateTime(List<Integer> cFansIds, Date startTime, Date endTime,
                                                         Integer type, List<Integer> bFasnId, List<Integer> groupId, String mallCode,
                                                         Boolean resp, Integer scene, Integer send, Integer start, Integer pageSize) {
        Query query = createQuery(cFansIds, startTime, endTime, type, bFasnId, groupId, mallCode, resp, scene, send);
        query.with(new Sort(new Sort.Order(Sort.Direction.DESC, "create_time")));
        if (start != null && start != 0) {
            query.skip(start);
        }
        if (pageSize != null && pageSize != 0) {
            query.limit(pageSize);
        }
        return mongoTemplate.find(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    public Long countChatSessionByCreateTime(List<Integer> cFansIds, Date startTime, Date endTime,
                                             Integer type, List<Integer> bFasnId, List<Integer> groupId, String mallCode,
                                             Boolean resp, Integer scene, Integer send) {
        Query query = createQuery(cFansIds, startTime, endTime, type, bFasnId, groupId, mallCode, resp, scene, send);
        return mongoTemplate.count(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    private Query createQuery(List<Integer> cFansIds, Date startTime, Date endTime,
                              Integer type, List<Integer> bFasnId, List<Integer> groupId, String mallCode,
                              Boolean resp, Integer scene, Integer send) {
        Query query = new Query();
        if (!CheckUtil.isEmpty(startTime) && !CheckUtil.isEmpty(endTime)) {
            query.addCriteria(Criteria.where("create_time").gt(startTime).lt(endTime));
        }
        if (cFansIds != null) {
            query.addCriteria(Criteria.where("c_fans_id").in(cFansIds));
        }
        if (type != null) {
            if (type == 4) {
                // 私聊
                if (bFasnId != null) {
                    query.addCriteria(Criteria.where("b_fans_id").in(bFasnId));
                } else {
                    query.addCriteria(Criteria.where("b_fans_id").exists(true));
                }
            } else if (type == 2) {
                // 群聊
                if (groupId != null) {
                    query.addCriteria(Criteria.where("group_id").in(groupId));
                } else {
                    query.addCriteria(Criteria.where("group_id").exists(true));
                }
            } else if (type == 1) {
                // 首页聊天
                query.addCriteria(Criteria.where("type").is(1));
                if (!CheckUtil.isEmpty(mallCode)) {
                    query.addCriteria(Criteria.where("mall_code").is(mallCode));
                }
            } else {
                Criteria criteria1 = Criteria.where("b_fans_id").in(bFasnId);
                Criteria criteria2 = Criteria.where("group_id").in(groupId);
                Criteria criteria3 = Criteria.where("mall_code").is(mallCode);
                if (bFasnId != null && groupId == null && CheckUtil.isEmpty(mallCode)) {
                    // 私聊
                    query.addCriteria(criteria1);
                } else if (bFasnId == null && groupId != null && CheckUtil.isEmpty(mallCode)) {
                    // 群聊
                    query.addCriteria(criteria2);
                } else if (!CheckUtil.isEmpty(mallCode) && bFasnId == null && groupId == null) {
                    // 首页聊天
                    query.addCriteria(criteria3);
                } else if (bFasnId != null && groupId != null && CheckUtil.isEmpty(mallCode)) {
                    // 私聊 + 群聊
                    Criteria criteria = new Criteria();
                    query.addCriteria(criteria.orOperator(criteria1, criteria2));
                } else if (bFasnId != null && groupId == null && !CheckUtil.isEmpty(mallCode)) {
                    // 私聊 + 首页聊天
                    Criteria criteria = new Criteria();
                    query.addCriteria(criteria.orOperator(criteria1, criteria3));
                } else if (bFasnId == null && groupId != null && !CheckUtil.isEmpty(mallCode)) {
                    // 群聊 + 首页聊天
                    Criteria criteria = new Criteria();
                    query.addCriteria(criteria.orOperator(criteria2, criteria3));
                }
                if (bFasnId != null && groupId != null && !CheckUtil.isEmpty(mallCode)) {
                    Criteria criteria = new Criteria();
                    query.addCriteria(criteria.orOperator(criteria1, criteria2, criteria3));
                }
            }
        }

        // 根据聊天发起的场景查找
        if (scene != null && scene != 0) {
            query.addCriteria(Criteria.where("scene").is(scene));
        }

        // 根据用户是否被响应查找
        if (resp != null) {
            query.addCriteria(Criteria.where("resp").is(resp));
        }

        if (send != null && send != 0) {
            if (send == 1) {
                query.addCriteria(Criteria.where("messages").exists(true));
            } else if (send == 2) {
                query.addCriteria(Criteria.where("messages").exists(false));
            }
        }
        return query;
    }

    /**
     * 查询B端导购员私聊的所有有效会话
     *
     * @param bFansId B端用户ID
     * @return 聊天会话
     */
    public List<ChatSession> findChatSessionByBFansIdAndEnable(Integer bFansId) {
        Query query = Query.query(Criteria.where("b_fans_id").is(bFansId).and("enable").is(true));
        query.fields().include("_id");
        return mongoTemplate.find(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);
    }

    /**
     * 查询商户前一天商户海报发言人数
     *
     * @return DailyMerchantPoster
     */
    public List<ChatSession> findMerchantPosterSessionDay(Date startTime,Date endTime) {
        Query query = new Query();
        query.addCriteria(new Criteria().orOperator(Criteria.where("scene").is(12).and("update_time").gte(startTime).and("enable").is(true)
                .andOperator(Criteria.where("update_time").lt(endTime)),Criteria.where("scene").is(12).and("create_time").lt(endTime).and("enable").is(false)));

        /*Query query = Query.query(Criteria.where("scene").is(12).and("update_time").gte(startTime).and("enable").is(true)
                .andOperator(Criteria.where("update_time").lt(endTime)).orOperator());*/
        return mongoTemplate.find(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);

    }

    /**
     * 查询商户上月商户海报发言人数
     *
     * @return DailyMerchantPoster
     */
    public List<ChatSession> findMerchantPosterSessionMonth(Date startTime,Date endTime) {
        Query query = new Query();
        query.addCriteria(new Criteria().orOperator(Criteria.where("scene").is(12).and("update_time").gte(startTime).and("enable").is(true)
                .andOperator(Criteria.where("update_time").lt(endTime)),Criteria.where("scene").is(12).and("create_time").lt(endTime).and("enable").is(false)));
     /*
        Query query = Query.query(Criteria.where("scene").is(12).and("update_time").gte(startTime)
                .andOperator(Criteria.where("update_time").lt(endTime)));*/
        return mongoTemplate.find(query, ChatSession.class, MongoConstant.COLLECTION_NAME_OF_CHAT_SESSION);


    }
}
